88 lines · 3.3 KB
1 ---
2 import Repo from '../../../../layouts/Repo.astro';
3 import { apiGet, apiPost } from '../../../../lib/api';
4
5 const { owner, repo } = Astro.params;
6 const cookie = Astro.request.headers.get('cookie') || '';
7
8 let branches: any[] = [];
9 let defaultBranch = 'main';
10 let error = '';
11
12 try {
13 const data = await apiGet(`/api/repos/${owner}/${repo}/branches`, cookie);
14 branches = data.branches || [];
15 defaultBranch = data.default_branch || 'main';
16 } catch (e: any) {
17 error = e.message;
18 }
19
20 if (Astro.request.method === 'POST') {
21 try {
22 const formData = await Astro.request.formData();
23 const title = formData.get('title') as string;
24 const description = formData.get('description') as string;
25 const source_branch = formData.get('source_branch') as string;
26 const target_branch = formData.get('target_branch') as string;
27
28 const { data } = await apiPost(
29 `/api/repos/${owner}/${repo}/merge-requests`,
30 { title, description, source_branch, target_branch },
31 cookie
32 );
33
34 return Astro.redirect(`/${owner}/${repo}/merge-requests/${data.number}`);
35 } catch (e: any) {
36 error = e.message;
37 }
38 }
39
40 const nonDefaultBranches = branches.filter((b: any) => !b.isDefault);
41 ---
42
43 <Repo owner={owner!} repo={repo!}>
44 <h2 style="font-size: 1.25rem; margin-bottom: 20px;">New merge request</h2>
45
46 {error && <div class="flash-error">{error}</div>}
47
48 <form method="POST" class="card">
49 <div style="display: flex; gap: 16px; margin-bottom: 20px; align-items: center;">
50 <div class="form-group" style="margin-bottom: 0; flex: 1;">
51 <label for="source_branch">Source branch</label>
52 <select id="source_branch" name="source_branch" required
53 style="width: 100%; padding: 8px 12px; background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius); color: var(--text); font-size: 0.875rem;">
54 {nonDefaultBranches.map((b: any) => (
55 <option value={b.name}>{b.name}</option>
56 ))}
57 {branches.filter((b: any) => b.isDefault).map((b: any) => (
58 <option value={b.name}>{b.name}</option>
59 ))}
60 </select>
61 </div>
62 <span style="color: var(--text-muted); font-size: 1.25rem; padding-top: 20px;">→</span>
63 <div class="form-group" style="margin-bottom: 0; flex: 1;">
64 <label for="target_branch">Target branch</label>
65 <select id="target_branch" name="target_branch" required
66 style="width: 100%; padding: 8px 12px; background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius); color: var(--text); font-size: 0.875rem;">
67 {branches.map((b: any) => (
68 <option value={b.name} selected={b.isDefault}>{b.name}</option>
69 ))}
70 </select>
71 </div>
72 </div>
73
74 <div class="form-group">
75 <label for="title">Title</label>
76 <input type="text" id="title" name="title" required placeholder="What does this merge request do?" />
77 </div>
78
79 <div class="form-group">
80 <label for="description">Description <span style="color: var(--text-muted); font-weight: normal;">(optional)</span></label>
81 <textarea id="description" name="description" rows="6" placeholder="Describe your changes..."
82 style="font-family: var(--font-sans);"></textarea>
83 </div>
84
85 <button type="submit" class="btn btn-primary">Create merge request</button>
86 </form>
87 </Repo>
88